package openjdk.thread;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * Created by mac on 2015/12/31.
 * 多线程设计我要注意如下:
 * 1.减少上下文的切换
 * 操作系统会给每一个执行的线程分配时间片，如果可运行的线程数大于机器的CPU数量，则操作系统可能会将某个正
 * 在运行的线程调度出来，使其它线程能够使用CPU,这样会产生上下文的切换。操作系统需要保存当前线程运行的上下
 * 文，并且给新调度进来的线程设置上下文。
 * 进行上下文的切换会有一定的调度开销，这个过程操作系统和JVM会消耗一定的CPU周期，并且由于CPU处理会
 * 缓存线程的一部分数据，当新的线程被切换进来时，它所需要的数据可能不在CPU的缓存中，因此还会导致CPU缓存的
 * 命中率下降。
 * 程序在进行锁等待或者被阻塞时，当前线程会挂起。因此如果锁的竞争激烈，或者线程频繁I/O阻塞，就可能导致
 * 上下文切换过于频繁，从而增加调度开销，降低程序的吞吐量。
 * <p>
 * 2.
 */
public class ThreadPool {
    private static void doStaff(int id) {
        System.out.println("String do " + id + " task...");
        try {
            Thread.sleep(1000 * 2);
        } catch (Exception e) {

        }
        System.out.println("Do task " + id + " finished.");
    }

    public static void main(String[] args) {
        // 创建了一个线程池里面有两个线程
        ExecutorService svc = Executors.newFixedThreadPool(2);

        for (int i = 0; i < 3; i++) {
            svc.submit(new Runnable() {
                @Override
                public void run() {
                    doStaff(8);
                }
            });
        }

        /**
         * 当主线程main结束时,调用svc.shutdown方法时不会关闭线程池，只有在其中的所有任务都完成时才会关闭。
         * 如果没有调用shutdown 方法，则在main 主线程退出后，应用（进程）将不会停止，因为线程池中
         * 还有线程在运行,此时当会产生大量的垃圾java进程，所以在项目中一定要执行showdown()方法.
         */

        svc.shutdown();
        System.out.println(">> main thread end.");

    }
}
